在整個前端開發過程中,包括 JavaScript, HTML, CSS 以及與後端的交互作用,安全性的考量在各個層面都至關重要。以下將針對不同語言在程式碼安全性應注意的撰寫原則:
輸入檢查與驗證:無論是從使用者輸入還是外部資料源,都應該進行嚴格的檢查與驗證。避免將不受信任的資料直接插入到 HTML 內容中。
輸出編碼:所有來自不受信任來源的輸出(特別是插入到 HTML、JavaScript、CSS 或 URL 中的資料)應該進行適當的編碼。例如,將 HTML 元素插入前進行 HTML 編碼,將屬性值進行屬性編碼。
HTML 編碼:將特殊字符如 <, >, &, ", ' 編碼為 HTML 實體(HTML Character Entity),如 <, >, &, ", ' 等。
範例:當使用者輸入某些內容並顯示在網頁中時,應該進行編碼。
<!-- 假設 userInput 是不受信任的使用者輸入 -->
<!-- 不正確的方式,容易被 XSS 攻擊 -->
<div>
User input: <span id="output">[userInput]</span>
</div>
<!-- 正確的方式,使用 HTML 編碼防止 XSS -->
<div>
User input: <span id="output"></span>
</div>
<script>
// 假設 userInput 是不受信任的使用者輸入
const userInput = '<script>alert("XSS")</script>';
// 使用 textContent 可以自動對 <script> 進行編碼,避免執行惡意程式碼。
document.getElementById('output').textContent = userInput;
</script>
JavaScript 編碼:避免將未經處理的數據插入到 JavaScript 中,特別是避免直接在 標籤或事件處理器中插入變數。
範例:將數據插入 JavaScript 時,如果是有潛在危險的 input 應先進行編碼再拼接。
<!-- 不正確的方式:容易被 XSS 攻擊 -->
<script>
var userInput = "[userInput]"; // 假設 userInput 來自不受信任的來源
eval(userInput); // 如果 userInput 包含惡意程式碼,將會被執行
</script>
<!-- 正確的方式:避免使用 eval() 或動態執行程式碼 -->
<script>
var userInput = '<script>alert("XSS")</script>';
// 安全地處理輸入
var safeInput = userInput.replace(/</g, "<").replace(/>/g, ">");
document.write(safeInput); // 顯示內容而不執行程式碼
</script>
// html 頁面上顯示:<script>alert("XSS")</script>
URL 編碼:將使用者輸入中的特殊字符在 URL 中進行編碼,防止 URL 攻擊。
範例:防止使用者輸入直接插入 URL 中。
<!-- 不正確的方式 -->
<a href="https://example.com/search?q=[userInput]">Search</a>
<!-- 正確的方式 -->
<a href="https://example.com/search?q=" id="searchLink">Search</a>
<script>
const userInput = '"><script>alert("XSS")</script>';
const encodedInput = encodeURIComponent(userInput);
document.getElementById('searchLink').href += encodedInput;
</script>
使用安全 API:當需要動態生成 HTML 時,優先使用 textContent 或 innerText,而非 innerHTML。例如:
// 不建議使用
element.innerHTML = "<div>" + userInput + "</div>";
// 建議使用
element.textContent = userInput;
避免內聯事件處理器:避免使用 onclick、onmouseover 等內聯事件,因為這可能存在 XSS 攻擊點,可使用 addEventListener 替代。
// 不建議
<button onclick="alert('Hello!')">Click me</button>
// 建議
const button = document.querySelector('button');
button.addEventListener('click', () => alert('Hello!'));
內容安全策略 (Content Security Policy, CSP):CSP 是一種安全機制,通過限制資源(如腳本、樣式表、圖片等)的加載,來防止 XSS 和其他類型的攻擊。可以透過 HTTP header 或 標籤來設置 CSP。
CSP 實例:後端可以透過 HTTP header 設置 CSP。
Content-Security-Policy: default-src 'self'; script-src 'self' https://trusted-scripts.com; object-src 'none';
default-src 'self':僅允許從與網頁相同的來源加載所有資源。
script-src 'self' https://trusted-scripts.com:僅允許從自己的域名和 https://trusted-scripts.com 加載 Script。
object-src 'none':禁止使用 , , 元素,防止 Flash 或其他Plugin 帶來的攻擊。
以 C# 為例,在 ASP.NET Core 中設置 CSP:
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
// 使用 Middleware 來設置 CSP header
app.Use(async (context, next) =>
{
context.Response.Headers.Add("Content-Security-Policy", "default-src 'self'; script-src 'self' https://trusted-scripts.com; object-src 'none'");
await next();
});
// 其他 Middleware...
app.UseRouting();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
CSP 實例:使用前端 html 的 tag 設定 CSP。
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self' https://trusted-scripts.com; object-src 'none';">
今天先介紹 XSS 攻擊樣態,並提供了幾個範例給大家參考,明天的文章將繼續探討程式碼安全性規則,例如:避免 Cross Site Request Forgery(CSRF)、避免使用不安全的 function、檢查第三方程式庫(third party library)安全性等。